"""
用户 | Token | 业务层
"""

import jwt

from config import settings
from models.other import JWTPayload
from models.po import UserTokenPO
from my_typing import *
from service import UserTokenService
from utils.data_utils.special import ObjectIdStr
from utils.mock_utils import DATETIME


class JWTHandler:
    """ JsonWebToken | 处理器 """

    @staticmethod
    def gen_payload(
        user_id: ObjectIdStr,
        token_max_age: int = settings.SECURITY.TOKEN_MAX_AGE,
    ) -> JWTPayload:
        """
        生成 Token 荷载

        Args:
            user_id: 用户 ID
            token_max_age: Token 有效时间（天）

        Returns:
            Token 荷载
        """

        issue_time: datetime = DATETIME.now()
        expire_time: datetime = issue_time + timedelta(days=token_max_age)

        return JWTPayload(
            subject=settings.CONST.PROJECT_NAME,
            token_max_age=token_max_age,
            issue_time=issue_time,
            expire_time=expire_time,
            user_id=user_id,
        )

    @staticmethod
    def gen_token_key(payload: JWTPayload) -> str:
        """
        生成 Token Key

        Args:
            payload: Token 荷载

        Returns:
            Token Key
        """

        return jwt.encode(
            payload=payload.model_dump(),
            key=settings.SECURITY.SECRET_KEY,
            algorithm=settings.SECURITY.ALGORITHM,
        )

    @staticmethod
    def get_payload_by_token_key(token_key: str) -> JWTPayload:
        """ 根据 Token Key 获取荷载 """

        payload_dic: dict = jwt.decode(
            jwt=token_key,
            key=settings.SECURITY.SECRET_KEY,
            algorithms=[settings.SECURITY.ALGORITHM],
        )

        return JWTPayload(**payload_dic)


class UserTokenHandler:
    """ 用户 | Token | 处理器 """

    @staticmethod
    def renew_user_token(
        user_token_po: UserTokenPO,
        renew_days: int,
    ) -> None:
        """
        Token 续期

        Args:
            user_token_po: Token PO
            renew_days: Token 续期天数
        """

        payload: JWTPayload = JWTHandler.gen_payload(user_token_po.user_id, renew_days)
        token_key: str = JWTHandler.gen_token_key(payload)
        user_token_po.key = token_key
        user_token_po.token_max_age = renew_days
        user_token_po.issue_time = DATETIME.now()
        user_token_po.expire_time = user_token_po.issue_time + timedelta(days=renew_days)
        UserTokenService.update_one(user_token_po)

    @staticmethod
    def create_user_token(
        user_id: ObjectIdStr,
        token_max_age: int = settings.SECURITY.TOKEN_MAX_AGE,
    ) -> UserTokenPO:
        """
        生成用户 Token

        Args:
            user_id: 用户 ID
            token_max_age: Token 有效时间（天）

        Returns:
            UserTokenPO
        """

        payload: JWTPayload = JWTHandler.gen_payload(user_id, token_max_age)
        token_key: str = JWTHandler.gen_token_key(payload)
        user_token_po = UserTokenPO(
            key=token_key,
            token_max_age=token_max_age,
            issue_time=payload.issue_time,
            expire_time=payload.expire_time,
            user_id=user_id,
        )
        UserTokenService.insert_one(user_token_po)

        return user_token_po

    @classmethod
    def get_or_create_user_token(
        cls,
        user_id: ObjectIdStr,
        token_max_age: int = settings.SECURITY.TOKEN_MAX_AGE,
    ) -> UserTokenPO:
        """
        获取/生成用户 Token

        Args:
            user_id: 用户 ID
            token_max_age: Token 有效时间（天）

        Returns:
            UserTokenPO
        """

        if user_token_po := UserTokenService.get_one_by_user_id(user_id):
            cls.renew_user_token(user_token_po, token_max_age)

            return user_token_po

        return cls.create_user_token(user_id, token_max_age)


if __name__ == "__main__":
    from devtools import debug

    debug(UserTokenHandler.create_user_token(ObjectIdStr()))
